package jdir.util;

import static jdir.util.LogUtil.begin;
import static jdir.util.LogUtil.end;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import jdir.exceptions.DestinationExists;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * This class handles our operations on the filesystem 
 * @author Marco Peroverde
 */
@SuppressWarnings("unused")
public class IOOperator
{
	private static Log		LOG		= LogFactory.getLog(IOOperator.class);
	private static Boolean	DEBUG	= LOG.isDebugEnabled();	
	private static Boolean	TRACE	= LOG.isTraceEnabled();

	/**
	 * Copys any file in the list to the destination. The given filelist will be reduced
	 * by the just copied file. This means that if an exception is thrown the fileList will hold
	 * all files which have not been copied till the exception occured.
	 * @param fileList source files
	 * @param targetPath path to where the files should go
	 * @param forceFirst force the first file to be overwritten
	 * @param forceAny force any file to be overwritten
	 * @throws DestinationExists if in the traget path the file is existing and overwriting is not forced
	 * @throws IOException on other IO errors
	 */
	public void copyFiles(List<File> fileList, PathGen targetPath, boolean forceFirst, boolean forceAny) throws DestinationExists, IOException{
		if(DEBUG)
			begin(LOG);
		
		while (fileList.size() > 0){
			copyFile(fileList.get(0), targetPath.getPath(), forceAny ? true : forceFirst);
			fileList.remove(0);
			if(forceFirst)
				forceFirst  = false;
		}
		if(DEBUG)
			end(LOG);
	}

	private void copyFile(File srcFile, String destPath, boolean force) throws DestinationExists, IOException {
		if(DEBUG)
			begin(LOG, "source: " + srcFile.getPath() + " target: " + destPath);
		
		File  destFile = new File(destPath + File.pathSeparator + srcFile.getName());
		if(destFile.exists())  { 
	         if(force)  { 
	        	 destFile.delete(); 
	         }  else  { 
	             throw  new  DestinationExists(destFile.getAbsolutePath()); 
	         }
	    }
		else
	         destFile.mkdirs();
		
		byte[]  buffer  =  new  byte[1024]; 
	     int  read  =  0; 
	     InputStream  in  =  null; 
	     OutputStream  out  =  null; 
	     try  { 
	         in  =  new  FileInputStream(srcFile); 
	         out  =  new  FileOutputStream(destFile); 
	         while(true)  { 
	             read  =  in.read(buffer); 
	             if  (read  ==  -1)  { 
	                 //-1  means end of stream
	                 break; 
	             } 
	             out.write(buffer,  0,  read); 
	         } 
	     }  finally  { 
	    	 /* 
	    	  * Exceptions can occure in the above try block. With this
	    	  * finally block it's ensured that the streams will be closed
	    	  * if they are still open
	    	  * 
	    	  */
	         if  (in  !=  null)
	        	 in.close(); 
	         if  (out  !=  null) 
	        	 out.close();
	         }	     
		
	     if(DEBUG)
			end(LOG);
		
	}
}
